package com.wht.sip.config;

import com.wht.sip.core.parser.GbStringMsgParserFactory;
import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Condition;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;

import javax.sip.*;
import java.util.Properties;
import java.util.TooManyListenersException;

/**
 * @author by HaiTao.Wang on 2025/9/11.
 */
@Slf4j
@Configuration
@Condition(onBean = SipConfig.class)
public class SipAutoConfiguration {

    @Bean
    public SipFactory sipFactory() {

        SipFactory instance = SipFactory.getInstance();
        instance.setPathName("gov.nist");
        return instance;
    }

    @Bean
    @Condition(onBean = SipFactory.class)
    public SipStackImpl createSipStackImpl(@Inject SipConfig sipConfig, @Inject SipFactory sipFactory) throws PeerUnavailableException {

        Properties sipProperties = SipProperties.getProperties(sipConfig.getIp(), "OFF");
        SipStackImpl sipStack = (SipStackImpl) sipFactory.createSipStack(sipProperties);
        sipStack.setMessageParserFactory(new GbStringMsgParserFactory());
        sipStack.setStackName("gb_starter");
        return sipStack;
    }

    @Bean("tcpSipProvider")
    @Condition(onBean = SipStackImpl.class)
    public SipProviderImpl startTcpListener(@Inject SipConfig sipConfig,
                                            @Inject SipStackImpl sipStack,
                                            @Inject SipListener sipProcessor) {
        try {
            ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getIp(), sipConfig.getPort(), ListeningPoint.TCP);
            SipProviderImpl tcpSipProvider = (SipProviderImpl) sipStack.createSipProvider(tcpListeningPoint);
            tcpSipProvider.setDialogErrorsAutomaticallyHandled();
            tcpSipProvider.addSipListener(sipProcessor);
            log.info("\033[36;2m「SIP」 tcp://{}:{} 启动成功\033[36;0m", sipConfig.getIp(), sipConfig.getPort());
            return tcpSipProvider;
        } catch (TransportNotSupportedException
                 | ObjectInUseException
                 | TooManyListenersException
                 | InvalidArgumentException e) {
            log.error("\033[31;2m[SIP] tcp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确\033[31;0m", sipConfig.getIp(), sipConfig.getPort());
        }
        return null;
    }

    @Bean("udpSipProvider")
    @Condition(onBean = SipStackImpl.class)
    public SipProviderImpl startUdpListener(@Inject SipConfig sipConfig,
                                            @Inject SipStackImpl sipStack,
                                            @Inject SipListener sipProcessor) {

        try {
            ListeningPoint udpListeningPoint = sipStack.createListeningPoint(sipConfig.getIp(), sipConfig.getPort(), ListeningPoint.UDP);
            SipProviderImpl udpSipProvider = (SipProviderImpl) sipStack.createSipProvider(udpListeningPoint);
            udpSipProvider.setDialogErrorsAutomaticallyHandled();
            udpSipProvider.addSipListener(sipProcessor);
            log.info("\033[36;2m「SIP」 upd://{}:{} 启动成功\033[36;0m", sipConfig.getIp(), sipConfig.getPort());
            return udpSipProvider;
        } catch (TransportNotSupportedException
                 | ObjectInUseException
                 | TooManyListenersException
                 | InvalidArgumentException e) {
            log.error("\033[31;2m[SIP] upd://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确\033[31;0m", sipConfig.getIp(), sipConfig.getPort());
        }
        return null;
    }

}
